#include <rtthread.h>
#include <drv_motor.h>
#include <drv_key.h>
#include <drv_beep.h>
#include <drv_aht10.h>
#include <drv_led.h>

#define STOP_ALARM      (0x01U << 1)
#define DATA_ABNORMAL   (0x01U << 2)

static rt_event_t alarm_event;
static rt_timer_t aht10_timer;
static rt_sem_t alarm_sem;
static float temp, humi;

static void aht10_thread_entry(void *parameter)
{
    while(1)
    {
        temp = aht10_read_temperature();
        humi = aht10_read_humidity();
        
        if (temp > 32 || humi > 82)
        {
                rt_event_send(alarm_event, DATA_ABNORMAL);
        }
        else
        {
            rt_sem_release(alarm_sem);
            rt_event_send(alarm_event, STOP_ALARM);
        }
        
        rt_thread_mdelay(10);
    }
}

static void alarm_thread_entry(void *parameter)
{
    rt_uint32_t set = 0;
    
    motor_stop();
    turn_off_led_r();
    turn_on_led_g();
    
    while (1)
    {
        if (rt_sem_take(alarm_sem, RT_WAITING_FOREVER) == RT_EOK)
        {
            if (rt_event_recv(alarm_event, DATA_ABNORMAL,
                RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
                RT_WAITING_FOREVER, &set) == RT_EOK)
            {
                motor_forward();
                turn_on_led_r();
                turn_off_led_g();
            }
        }
    }
}

static void stop_alarm_thread_entry(void *parameter)
{
    rt_uint32_t set = 0;
    
    while (1)
    {
        if (rt_event_recv(alarm_event, STOP_ALARM,
            RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR,
            RT_WAITING_FOREVER, &set) == RT_EOK)
        {
            rt_sem_take(alarm_sem, RT_WAITING_FOREVER);
            motor_stop();
            turn_off_led_r();
            turn_on_led_g();
        }
    }
}

static void key_thread_entry(void *parameter)
{
    rt_uint8_t whichkey;
    static rt_uint8_t timer_control_key_value = 0;
    
    while (1)
    {
        whichkey = key_scan(0);
        if (whichkey == KEY0_PRES)
        {
            rt_sem_release(alarm_sem);
            rt_event_send(alarm_event, STOP_ALARM);
        }
        
        if (whichkey == KEY1_PRES)
        {
            switch (timer_control_key_value)
            {
                case 1:
                    rt_timer_start(aht10_timer);
                    rt_kprintf("start printing aht10 data.\n");
                    timer_control_key_value = 0;
                    break;
                case 0:
                    rt_timer_stop(aht10_timer);
                    rt_kprintf("stop printing aht10 data.\n");
                    timer_control_key_value = 1;
                    break;
            }
        }
        rt_thread_mdelay(10);
    }
}

static void aht10_timeout_entry(void *parameter)
{
    rt_kprintf("timestamp: %d\n", rt_tick_get());
    rt_kprintf("/*******************/\n");
    rt_kprintf("/* TEMP = %2d.%d C   */\n", (int)(temp * 10) / 10, (int)(temp * 10) % 10);
    rt_kprintf("/* HUMI = %2d.%d %RH */\n", (int)(humi * 10) / 10, (int)(humi * 10) % 10);
    rt_kprintf("/*******************/\n\n");
}

int main(void)
{
    rt_thread_t key_thread, alarm_thread, stop_alarm_thread, aht10_thread;

    alarm_event = rt_event_create("alarmevent", RT_IPC_FLAG_FIFO);
    if (alarm_event == RT_NULL) rt_kprintf("alarm_event create failed!\n");
    
    alarm_sem = rt_sem_create("alarmsem", 1, RT_IPC_FLAG_FIFO);
    if (alarm_sem == RT_NULL) rt_kprintf("alarm_sem create failed!\n");
    
    aht10_thread = rt_thread_create("aht10data", aht10_thread_entry, RT_NULL,
                                    512, RT_THREAD_PRIORITY_MAX / 2, 20);
    if (aht10_thread != RT_NULL) rt_thread_startup(aht10_thread);
    else rt_kprintf("aht10_thread create failed!\n");
    
    alarm_thread = rt_thread_create("alarm", alarm_thread_entry, RT_NULL,
                                    512, RT_THREAD_PRIORITY_MAX / 2 - 2, 20);
    if (alarm_thread != RT_NULL) rt_thread_startup(alarm_thread);
    else rt_kprintf("alarm_thread create failed!\n");
    
    stop_alarm_thread = rt_thread_create("stopalarm", stop_alarm_thread_entry, RT_NULL,
                                    512, RT_THREAD_PRIORITY_MAX/ 2 + 1, 20);
    if (stop_alarm_thread != RT_NULL) rt_thread_startup(stop_alarm_thread);
    else rt_kprintf("stop_alarm_thread create failed!\n");
    
    key_thread = rt_thread_create("keyscan", key_thread_entry, RT_NULL,
                                  256, RT_THREAD_PRIORITY_MAX / 2 - 1 , 20);
    if (key_thread != RT_NULL) rt_thread_startup(key_thread);
    else rt_kprintf("key_thread create failed!\n");

    aht10_timer = rt_timer_create("aht10timer", aht10_timeout_entry, RT_NULL,
                                  1000, RT_TIMER_CTRL_SET_PERIODIC);
    if (aht10_timer != RT_NULL) rt_timer_start(aht10_timer);
    else rt_kprintf("aht10_timer create failed!\n");
}
